import 'package:casdon/common/state/common_net_status.dart';
import 'package:casdon/core/auth/auth_storage.dart';
import 'package:casdon/core/extentions/string_validation.dart';
import 'package:casdon/core/logger/log.dart';
import 'package:casdon/core/network/business_exception.dart';
import 'package:casdon/modules/home/application/notification/tuya_auth_notifier.dart';
import 'package:casdon/modules/login/application/notifier/login_notifier.dart';
import 'package:casdon/modules/login/data/api/login_api.dart';
import 'package:casdon/modules/login/data/api/valide_code_type.dart';
import 'package:casdon/modules/login/domain/states/login_apple_state.dart';
import 'package:casdon/modules/login/domain/states/login_code_state.dart';
import 'package:casdon/modules/login/domain/usecases/login_usecase.dart';
import 'package:casdon/modules/login/domain/usecases/verify_otp_usecase.dart';
import 'package:casdon/modules/login/providers/login_code_provider.dart';
import 'package:casdon/modules/login/providers/login_provider.dart';
import 'package:sign_in_with_apple/sign_in_with_apple.dart';

enum AppleLoginStep { auth, login, sendCode, verifyCode, afterbindingLogin }

class LoginAppleNotifier extends LoginNotifier<LoginAppleState> {
  AppleLoginStep step = AppleLoginStep.auth;
  Future<void> signIn() async {
    step = AppleLoginStep.auth;
    state = state.copyWith(
      status: CommonNetStatus.idle,
      message: null,
      errorCode: null,
      socialCode: null,
      socialState: null,
      account: null,
      code: null,
    );
    if (isLoading()) {
      return;
    }

    if (false == state.agreed) {
      setFailure(msg: "请先同意用户协议");
      return;
    }

    setLoading();

    try {
      final credential = await SignInWithApple.getAppleIDCredential(
        scopes: [
          AppleIDAuthorizationScopes.email,
          AppleIDAuthorizationScopes.fullName,
        ],
      );
      _onSignedIn(credential);
    } on SignInWithAppleAuthorizationException catch (e) {
      // 注意这里捕获的是 AuthorizationError
      if (e.code == AuthorizationErrorCode.canceled) {
        Log.i('用户取消登录');
        setFailure(msg: "用户取消登录");
      } else {
        Log.e('Apple 登录错误', e.toString(), StackTrace.current);
        setFailure(msg: "授权失败");
      }
    } catch (e) {
      Log.e('Apple 登录异常', e.toString(), StackTrace.current);
      setFailure(msg: "授权失败");
    }
  }

  Future<void> _onSignedIn(AuthorizationCredentialAppleID credential) async {
    // setSuccess("苹果授权成功");
    Log.i('---------- Apple 登录凭据 ----------');

    Log.i('User Identifier: ${credential.userIdentifier}');
    Log.i('Identity Token: ${credential.identityToken}');
    Log.i('Authorization Code: ${credential.authorizationCode}');

    if (credential.email != null) {
      Log.i('Email: ${credential.email}');
    }
    if (credential.givenName != null) {
      Log.i('Given Name: ${credential.givenName}');
      Log.i('Family Name: ${credential.familyName}');
    }
    state = state.copyWith(
      socialCode: credential.authorizationCode,
      socialState: "123123121231",
    );
    Log.i('------------------------------------');

    login();
  }

  void login() async {
    if (step == AppleLoginStep.auth) {
      step = AppleLoginStep.login;
    } else if (step == AppleLoginStep.verifyCode) {
      step = AppleLoginStep.afterbindingLogin;
    } else {
      Log.e(
        "apple登录步骤错误,当前非AppleLoginStep.verifyCode,AppleLoginStep.auth",
        Object(),
        StackTrace.current,
      );
      return;
    }

    state = state.copyWith(
      status: CommonNetStatus.idle,
      message: null,
      errorCode: null,
    );

    setLoading();
    try {
      LoginUsecase loginUsecase = ref.read(loginUsecaseProvider);
      RequestLogin request = RequestLogin(
        grantType: LoginGrantType.social.name,
        socialCode: state.socialCode,
        socialState: state.socialState,
        source: LoginSource.appleid.name,
        userName: state.account,
      );
      final ret = await loginUsecase.execute(request);

      final authStorage = ref.read(authStorageProvider.notifier);
      await authStorage.saveToken(ret.access_token);

      await ref.read(tuyaLoginProvider.notifier).login();
      final tuyaSuccess = ref.read(tuyaLoginStateProvider);
      if (!tuyaSuccess) {
        setFailure(msg: "登录失败，请稍后再试！");
        return;
      }
      setSuccess("登录成功");
    } on BusinessException catch (e) {
      setFailure(errorCode: e.code, msg: e.msg);
    } catch (e) {
      setFailure(msg: "登录失败，请稍后再试！");
    }
  }

  void verifyCode() async {
    if (step == AppleLoginStep.sendCode) {
      step = AppleLoginStep.verifyCode;
    } else {
      Log.e(
        "apple登录步骤错误,AppleLoginStep.sendCode步骤",
        Object(),
        StackTrace.current,
      );
      return;
    }
    state = state.copyWith(
      status: CommonNetStatus.idle,
      message: null,
      errorCode: null,
    );
    setLoading();
    try {
      VerifyOtpUsecase verifyUsecase = ref.read(verifyOtpUsecaseProvider);
      final ret = await verifyUsecase.execute(
        state.account!,
        state.code!,
        ValideCodeType.login,
      );

      if (ret == true) {
        setSuccess("验证码正确");
      } else {
        setFailure(msg: "验证码错误");
      }
    } on BusinessException catch (e) {
      setFailure(errorCode: e.code, msg: e.msg);
    } catch (e) {
      setFailure(msg: "验证码校验失败");
      Log.e("验证码校验失败", e.toString(), StackTrace.current);
    }
  }

  // 绑定微信时，发送验证码
  void sendCode({SendCodeSource source = SendCodeSource.accountPage}) {
    step = AppleLoginStep.sendCode;

    state = state.copyWith(
      status: CommonNetStatus.idle,
      message: null,
      errorCode: null,
      code: null,
    );

    if (state.account == null) {
      return;
    }

    if (state.account!.isEmail() == true) {
      _sendEmailCode();
      return;
    }

    if (state.account!.isPhoneNum() == true) {
      _sendSMSCode();
      return;
    }

    setFailure(msg: "账号格式错误");
  }

  void updateCode(String value) {
    state = state.copyWith(
      code: value,
      version: state.version,
      status: CommonNetStatus.idle,
    );
  }

  // 设置账户，因为不需要触发重建或者响应，所以版本号不变
  void setAccount(String account) {
    state = state.copyWith(
      status: CommonNetStatus.idle,
      message: "",
      account: account,
      version: state.version,
      agreed: state.agreed,
      errorCode: "",
    );
  }

  void setCode(String code) {
    state = state.copyWith(
      status: CommonNetStatus.idle,
      message: "",
      account: state.account,
      code: code,
      version: state.version,
      agreed: state.agreed,
      errorCode: "",
    );
  }

  void _sendEmailCode() async {
    if (state.account == null) {
      return;
    }
    setLoading();
    try {
      final emailUsecase = ref.read(sendEmailcodeProvider);

      final ret = await emailUsecase.execute(
        state.account!,
        ValideCodeType.login,
      );
      ret ? setSuccess("发送验证码成功") : setFailure(msg: "发送验证码失败，请稍后再试！");
    } on BusinessException catch (e) {
      setFailure(errorCode: e.code, msg: e.msg);
    } catch (e) {
      setFailure(msg: "发送验证码失败，请稍后再试！");
    }
  }

  void _sendSMSCode() async {
    if (state.account == null) {
      return;
    }
    setLoading();
    try {
      final smsUsecase = ref.read(sendSmsUsecaseProvider);

      final ret = await smsUsecase.execute(
        state.account!,
        ValideCodeType.login,
      );
      ret.success ? setSuccess("发送验证码成功") : setFailure(msg: "发送验证码失败，请稍后再试！");
    } on BusinessException catch (e) {
      setFailure(errorCode: e.code, msg: e.msg);
    } catch (e) {
      setFailure(msg: "发送验证码失败，请稍后再试！");
    }
  }

  void resetStateAndStep() {
    step = AppleLoginStep.auth;
    state = state.copyWith(
      status: CommonNetStatus.idle,
      message: null,
      errorCode: null,
      socialCode: null,
      socialState: null,
      account: null,
      code: null,
    );
  }

  @override
  LoginAppleState build() {
    ref.onDispose(() {
      Log.d("已经销毁：LoginAppleState");
    });
    return LoginAppleState.initial();
  }
}
